package org.wattdepot.cli;

import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClientException;
import org.wattdepot.util.tstamp.Tstamp;

/**
 * Executes the power statistics command.
 * 
 * @author Scott Wong and Kelli Sawai
 * 
 */
public class PowerStats extends CommandLineInterface implements WattDepotCliCommand {

  /**
   * Executes and returns the results of the power statistics command.
   * 
   * @param args The arguments required to execute this method.
   * @return The results of the command.
   */
  public String doCommand(String args) {
    try {
      if (args.matches("powerstats [generated | consumed]+ \\w* day \\S* "
          + "sampling-interval \\d* statistic [min | max | average]+")) {
        String[] data = args.split(" ");
        String type = data[1];
        String sourceName = data[2];
        String day = data[4];
        int interval = Integer.decode(data[6]).intValue();
        String statistic = data[8];
        return listPowerDay(type, sourceName, day, interval, statistic);
      }
      else {
        return "The command you have entered is invalid.";
      }
    }
    catch (WattDepotClientException e) {
      return "An error occured while executing the requested command.";
    }
    catch (Exception e) {
      return "An error occured while executing the requested command.";
    }
  }

  /**
   * Lists the power generated or consumed at given timestamps.
   * 
   * @param type If the power is generated or consumed.
   * @param source The name of the plant data is taken from.
   * @param date The day to be looked up.
   * @param interval The time interval at which to sample.
   * @param stat The min, max or average of the data.
   * @return The list of power generated or consumed at a given timestamp.
   * @throws WattDepotClientException if there is an error encountered by the WattDepotCli server.
   * 
   */
  private String listPowerDay(String type, String source, String date, int interval,
      String stat) throws WattDepotClientException {
    double result = 0;

    try {
      // sets the start, end and current interval date.
      XMLGregorianCalendar startDate = toTimestamp(date);
      XMLGregorianCalendar curTime = startDate;

      // Check if the timestamp is in the future.
      XMLGregorianCalendar now =
          DatatypeFactory.newInstance()
              .newXMLGregorianCalendar(new GregorianCalendar());
      if (startDate.compare(now) >= 0) {
        return futureTimestampMessage;
      }
      // sets the size of the array to store the data.
      int size = 1440 / interval;
      double[] dayData = new double[size];

      // if the specified data summary is power consumed.
      if (type.compareToIgnoreCase("consumed") == 0) {
        // loop that adds the data to the storage array.
        for (int i = 0; i < size; i++) {
          dayData[i] = client.getPowerConsumed(source, curTime);
          curTime = Tstamp.incrementMinutes(curTime, interval);
        }
        // if the specified data summary is power generated.
      }
      else {
        // loop that adds the data to the storage array.
        for (int i = 0; i < size; i++) {
          dayData[i] = client.getPowerGenerated(source, curTime);
          curTime = Tstamp.incrementMinutes(curTime, interval);
        }
      }

      // if the data summary requested is the smallest data number.
      if (stat.compareToIgnoreCase("min") == 0) {
        double temp;
        double smallest = 0;
        smallest = dayData[0];

        // loop that finds the smallest number in the data.
        for (int i = 0; i < size; i++) {
          // if the end of the array is reached.
          if ((i + 1) == size) {
            temp = smallest;
          }
          else {
            temp = dayData[i + 1];
          }
          if (temp < smallest) {
            smallest = temp;
          }
        }
        result = smallest;
      }

      // if the data summary requested is the largest data number.
      if (stat.compareToIgnoreCase("max") == 0) {
        double temp;
        double largest = 0;
        largest = dayData[0];

        // loop that finds the largest number in the data.
        for (int i = 0; i < size; i++) {
          // if the end of the array is reached.
          if ((i + 1) == size) {
            break;
          }
          else {
            temp = dayData[i + 1];
          }
          if (temp > largest) {
            largest = temp;
          }
        }
        result = largest;
      }

      // if the data summary requested is the average of the data.
      if (stat.compareToIgnoreCase("average") == 0) {
        double temp = 0;

        // adds up all the data.
        for (int i = 0; i < size; i++) {
          temp += dayData[i];
        }
        // finds and prints the average of the data numbers.
        result = (temp / size);
      }
    }
    catch (ResourceNotFoundException e) {
      return resourceMessage;
    }
    catch (DatatypeConfigurationException e) {
      e.printStackTrace();
    }

    return Double.toString(result);
  }

}
